
#include "type.h"
#include "value_move_config.h"

#define current_value	   0
#define target_value		1
#define interval_value		 2
#define interval_ticks		   4
#define interval_tick_counter		  5

#define OFFSET			  6

static volatile uint16_t VALUE_MOVES[VALUE_MOVE_NUM_MAX*OFFSET];

void value_move_init(void)
{
	uint8_t i;
	for (i = 0; i < VALUE_MOVE_NUM_MAX*OFFSET; i++) {
		VALUE_MOVES[i] = 0;
	}
}

void value_move_tick_handler(void)
{
	uint8_t i;
	uint8_t j;
	for (i = 0; i < VALUE_MOVE_NUM_MAX; i++) {
		j = i*OFFSET;
		if(VALUE_MOVES[j+current_value] == VALUE_MOVES[j+target_value]){
			if(VALUE_MOVES[j+circle_move_flag] == 0){
				continue;
			}
			else{
				if(VALUE_MOVES[j+target_value] == VALUE_MOVES[j+begin_value]){
					VALUE_MOVES[j+target_value] = VALUE_MOVES[j+end_value];
				}
				else{
					VALUE_MOVES[j+target_value] = VALUE_MOVES[j+begin_value];
				}
			}
		}

		if(VALUE_MOVES[j+current_value] > VALUE_MOVES[j+target_value]){
			if(VALUE_MOVES[j+current_value] - VALUE_MOVES[j+target_value] > VALUE_MOVES[j+step_value]){
				VALUE_MOVES[j+current_value] -= VALUE_MOVES[j+step_value];
			}
			else{
				VALUE_MOVES[j+current_value] = VALUE_MOVES[j+target_value];
			}
			value_move_value_changed_event(i, VALUE_MOVES[j+current_value]);
		}
		else if(VALUE_MOVES[j+current_value] < VALUE_MOVES[j+target_value]){
			if(VALUE_MOVES[j+target_value] - VALUE_MOVES[j+current_value] > VALUE_MOVES[j+step_value]){
				VALUE_MOVES[j+current_value] += VALUE_MOVES[j+step_value];
			}
			else{
				VALUE_MOVES[j+current_value] = VALUE_MOVES[j+target_value];
			}
			value_move_value_changed_event(i, VALUE_MOVES[j+current_value]);
		}
	}
}

//move_ticks: how many ticks will take to move "current_value" to "target_value"
void value_move_to_value_by_tick(uint8_t value_move_num, uint16_t set_target_value, uint16_t move_ticks)
{
	uint8_t j;
	j = value_move_num*OFFSET;
	if(VALUE_MOVES[j+current_value] == set_target_value){
		return;
	}
	if(move_ticks > 0){
		if(VALUE_MOVES[j+current_value] > set_target_value){
			VALUE_MOVES[j+step_value] = VALUE_MOVES[j+current_value] - set_target_value;
		}
		else if(VALUE_MOVES[j+current_value] < set_target_value){
			VALUE_MOVES[j+step_value] = set_target_value - VALUE_MOVES[j+current_value];
		}
		if(VALUE_MOVES[j+step_value] > move_ticks){
			VALUE_MOVES[j+step_value] = VALUE_MOVES[j+step_value]/move_ticks;
		}
		else{
			VALUE_MOVES[j+step_value] = 1;
		}
	}
	else{
		VALUE_MOVES[j+current_value] = set_target_value;
		value_move_value_changed_event(value_move_num, VALUE_MOVES[j+current_value]);
	}
	VALUE_MOVES[j+target_value] = set_target_value;
}

//set_step_value: how many steps pre tick
void value_move_to_value_by_step(uint8_t value_move_num, uint16_t set_target_value, uint16_t set_step_value)
{
	uint8_t j;
	j = value_move_num*OFFSET;
	if(VALUE_MOVES[j+current_value] == set_target_value){
		return;
	}
	if(set_step_value > 0){
		if(VALUE_MOVES[j+current_value] > set_target_value){
			if(set_step_value > (VALUE_MOVES[j+current_value] - set_target_value)){
				set_step_value = VALUE_MOVES[j+current_value] - set_target_value;
			}
		}
		else if(VALUE_MOVES[j+current_value] < set_target_value){
			if(set_step_value > (set_target_value - VALUE_MOVES[j+current_value])){
				set_step_value = set_target_value - VALUE_MOVES[j+current_value];
			}
		}
		VALUE_MOVES[j+step_value] = set_step_value;
	}
	VALUE_MOVES[j+target_value] = set_target_value;
}

//the "current_value" move to the "begin_value" in the first round
//period_ticks: how many ticks will take to move "begin_value" to "end_value"
void value_move_circle_move_by_tick(uint8_t value_move_num, uint16_t set_begin_value, uint16_t set_end_value, uint16_t period_ticks)
{
	uint16_t all_steps;
	uint8_t j;
	if(set_begin_value == set_end_value){
		return;
	}

	if(set_begin_value > set_end_value){
		all_steps = set_begin_value - set_end_value;
	   }
	else{
		all_steps = set_end_value - set_begin_value;
	}
	if(all_steps > period_ticks){
		all_steps = all_steps/period_ticks;
	}
	else{
		all_steps = 1;
	}

	if(period_ticks > 0){
		j = value_move_num*OFFSET;
		VALUE_MOVES[j+begin_value] = set_begin_value;
		VALUE_MOVES[j+end_value] = set_end_value;
		VALUE_MOVES[j+step_value] = all_steps;
		VALUE_MOVES[j+circle_move_flag] = 1;
		VALUE_MOVES[j+target_value] = set_begin_value;
	}
}

//the "current_value" move to the "begin_value" in the first round
//set_step_value: how many steps pre tick
void value_move_circle_move_by_step(uint8_t value_move_num, uint16_t set_begin_value, uint16_t set_end_value, uint16_t set_step_value)
{
	uint8_t j;
	if(set_begin_value == set_end_value){
		return;
	}
	if(set_step_value > 0){
		j = value_move_num*OFFSET;
		VALUE_MOVES[j+begin_value] = set_begin_value;
		VALUE_MOVES[j+end_value] = set_end_value;
		VALUE_MOVES[j+step_value] = set_step_value;
		VALUE_MOVES[j+circle_move_flag] = 1;
		VALUE_MOVES[j+target_value] = set_begin_value;
	}
}

void value_move_stop_move(uint8_t value_move_num)
{
	value_move_num = value_move_num*OFFSET;
	VALUE_MOVES[value_move_num+circle_move_flag] = 0;
	VALUE_MOVES[value_move_num+target_value] = VALUE_MOVES[value_move_num+current_value];
}
